/**
 * https://www.dowebok.com/134.html
 */
layui.define(function(exports) {
	var moduleName = 'scrollReveal';

	var scrollReveal = (function(window) {

		'use strict';

		// generator (increments) for the next scroll-reveal-id
		var nextId = 1;

		/**
		 * RequestAnimationFrame polyfill
		 * @function
		 * @private
		 */
		var requestAnimFrame = (function() {
			return window.requestAnimationFrame ||
				window.webkitRequestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				function(callback) {
					window.setTimeout(callback, 1000 / 60);
				};
		}());

		function scrollReveal(options) {

			this.options = this.extend(this.defaults, options);
			this.docElem = this.options.elem;
			this.styleBank = {};

			if (this.options.init == true) this.init();
		}

		scrollReveal.prototype = {

			defaults: {
				after: '0s',
				enter: 'bottom',
				move: '24px',
				over: '0.66s',
				easing: 'ease-in-out',
				opacity: 0,
				complete: function() {},

				//  if 0, the element is considered in the viewport as soon as it enters
				//  if 1, the element is considered in the viewport when it's fully visible
				viewportFactor: 0.33,

				// if false, animations occur only once
				// if true, animations occur each time an element enters the viewport
				reset: false,

				// if true, scrollReveal.init() is automaticaly called upon instantiation
				init: true,
				elem: window.document.documentElement
			},

			/*=============================================================================*/

			init: function() {

				this.scrolled = false;

				var self = this;

				//  Check DOM for the data-scrollReveal attribute
				//  and initialize all found elements.
				this.elems = Array.prototype.slice.call(this.docElem.querySelectorAll(
					'[data-scroll-reveal]'));
				this.elems.forEach(function(el, i) {

					//  Capture original style attribute
					var id = el.getAttribute("data-scroll-reveal-id");
					if (!id) {
						id = nextId++;
						el.setAttribute("data-scroll-reveal-id", id);
					}
					if (!self.styleBank[id]) {
						self.styleBank[id] = el.getAttribute('style');
					}

					self.update(el);
				});

				var scrollHandler = function(e) {
					// No changing, exit
					if (!self.scrolled) {
						self.scrolled = true;
						requestAnimFrame(function() {
							self._scrollPage();
						});
					}
				};

				var resizeHandler = function() {

					//  If we’re still waiting for settimeout, reset the timer.
					if (self.resizeTimeout) {
						clearTimeout(self.resizeTimeout);
					}

					function delayed() {
						self._scrollPage();
						self.resizeTimeout = null;
					}
					self.resizeTimeout = setTimeout(delayed, 200);
				};

				// captureScroll
				if (this.docElem == window.document.documentElement) {
					window.addEventListener('scroll', scrollHandler, false);
					window.addEventListener('resize', resizeHandler, false);
				} else {
					this.docElem.addEventListener('scroll', scrollHandler, false);
				}
			},

			/*=============================================================================*/

			_scrollPage: function() {
				var self = this;

				this.elems.forEach(function(el, i) {
					self.update(el);
				});
				this.scrolled = false;
			},

			/*=============================================================================*/

			parseLanguage: function(el) {

				//  Splits on a sequence of one or more commas or spaces.
				var words = el.getAttribute('data-scroll-reveal').split(/[, ]+/),
					parsed = {};

				function filter(words) {
					var ret = [],

						blacklist = [
							"from",
							"the",
							"and",
							"then",
							"but",
							"with"
						];

					words.forEach(function(word, i) {
						if (blacklist.indexOf(word) > -1) {
							return;
						}
						ret.push(word);
					});

					return ret;
				}

				words = filter(words);

				words.forEach(function(word, i) {

					switch (word) {
						case "enter":
							parsed.enter = words[i + 1];
							return;

						case "after":
							parsed.after = words[i + 1];
							return;

						case "wait":
							parsed.after = words[i + 1];
							return;

						case "move":
							parsed.move = words[i + 1];
							return;

						case "ease":
							parsed.move = words[i + 1];
							parsed.ease = "ease";
							return;

						case "ease-in":
							parsed.move = words[i + 1];
							parsed.easing = "ease-in";
							return;

						case "ease-in-out":
							parsed.move = words[i + 1];
							parsed.easing = "ease-in-out";
							return;

						case "ease-out":
							parsed.move = words[i + 1];
							parsed.easing = "ease-out";
							return;

						case "over":
							parsed.over = words[i + 1];
							return;

						default:
							return;
					}
				});

				return parsed;
			},


			/*=============================================================================*/

			update: function(el) {

				var that = this;
				var css = this.genCSS(el);
				var style = this.styleBank[el.getAttribute("data-scroll-reveal-id")];

				if (style != null) style += ";";
				else style = "";

				if (!el.getAttribute('data-scroll-reveal-initialized')) {
					el.setAttribute('style', style + css.initial);
					el.setAttribute('data-scroll-reveal-initialized', true);
				}

				if (!this.isElementInViewport(el, this.options.viewportFactor)) {
					if (this.options.reset) {
						el.setAttribute('style', style + css.initial + css.reset);
					}
					return;
				}

				if (el.getAttribute('data-scroll-reveal-complete')) return;

				if (this.isElementInViewport(el, this.options.viewportFactor)) {
					el.setAttribute('style', style + css.target + css.transition);
					//  Without reset enabled, we can safely remove the style tag
					//  to prevent CSS specificy wars with authored CSS.
					if (!this.options.reset) {
						setTimeout(function() {
							if (style != "") {
								el.setAttribute('style', style);
							} else {
								el.removeAttribute('style');
							}
							el.setAttribute('data-scroll-reveal-complete', true);
							that.options.complete(el);
						}, css.totalDuration);
					}
					return;
				}
			},

			/*=============================================================================*/

			genCSS: function(el) {
				var parsed = this.parseLanguage(el),
					enter,
					axis;

				if (parsed.enter) {

					if (parsed.enter == "top" || parsed.enter == "bottom") {
						enter = parsed.enter;
						axis = "y";
					}

					if (parsed.enter == "left" || parsed.enter == "right") {
						enter = parsed.enter;
						axis = "x";
					}

				} else {

					if (this.options.enter == "top" || this.options.enter == "bottom") {
						enter = this.options.enter
						axis = "y";
					}

					if (this.options.enter == "left" || this.options.enter == "right") {
						enter = this.options.enter
						axis = "x";
					}
				}

				//  After all values are parsed, let’s make sure our our
				//  pixel distance is negative for top and left entrances.
				//
				//  ie. "move 25px from top" starts at 'top: -25px' in CSS.

				if (enter == "top" || enter == "left") {
					if (parsed.move) {
						parsed.move = "-" + parsed.move;
					} else {
						parsed.move = "-" + this.options.move;
					}
				}

				var dist = parsed.move || this.options.move,
					dur = parsed.over || this.options.over,
					delay = parsed.after || this.options.after,
					easing = parsed.easing || this.options.easing,
					opacity = parsed.opacity || this.options.opacity;

				var transition = "-webkit-transition: -webkit-transform " + dur + " " + easing +
					" " + delay + ",  opacity " + dur + " " + easing + " " + delay + ";" +
					"transition: transform " + dur + " " + easing + " " + delay + ", opacity " +
					dur + " " + easing + " " + delay + ";" +
					"-webkit-perspective: 1000;" +
					"-webkit-backface-visibility: hidden;";

				//  The same as transition, but removing the delay for elements fading out.
				var reset = "-webkit-transition: -webkit-transform " + dur + " " + easing +
					" 0s,  opacity " + dur + " " + easing + " " + delay + ";" +
					"transition: transform " + dur + " " + easing + " 0s,  opacity " + dur +
					" " + easing + " " + delay + ";" +
					"-webkit-perspective: 1000;" +
					"-webkit-backface-visibility: hidden;";

				var initial = "-webkit-transform: translate" + axis + "(" + dist + ");" +
					"transform: translate" + axis + "(" + dist + ");" +
					"opacity: " + opacity + ";";

				var target = "-webkit-transform: translate" + axis + "(0);" +
					"transform: translate" + axis + "(0);" +
					"opacity: 1;";
				return {
					transition: transition,
					initial: initial,
					target: target,
					reset: reset,
					totalDuration: ((parseFloat(dur) + parseFloat(delay)) * 1000)
				};
			},

			getViewportH: function() {
				var client = this.docElem['clientHeight'],
					inner = window['innerHeight'];

				if (this.docElem == window.document.documentElement)
					return (client < inner) ? inner : client;
				else
					return client;
			},

			getOffset: function(el) {
				var offsetTop = 0,
					offsetLeft = 0;

				do {
					if (!isNaN(el.offsetTop)) {
						offsetTop += el.offsetTop;
					}
					if (!isNaN(el.offsetLeft)) {
						offsetLeft += el.offsetLeft;
					}
				} while (el = el.offsetParent)

				return {
					top: offsetTop,
					left: offsetLeft
				}
			},

			isElementInViewport: function(el, h) {
				var scrolled = this.docElem.scrollTop + this.docElem.offsetTop;
				if (this.docElem == window.document.documentElement) scrolled = window
					.pageYOffset;
				var
					viewed = scrolled + this.getViewportH(),
					elH = el.offsetHeight,
					elTop = this.getOffset(el).top,
					elBottom = elTop + elH,
					h = h || 0;

				return (elTop + elH * h) <= viewed &&
					(elBottom) >= scrolled ||
					(el.currentStyle ? el.currentStyle : window.getComputedStyle(el, null))
					.position == 'fixed';
			},

			extend: function(a, b) {
				for (var key in b) {
					if (b.hasOwnProperty(key)) {
						a[key] = b[key];
					}
				}
				return a;
			}
		}; // end scrollReveal.prototype

		return scrollReveal;
	})(window);



	exports(moduleName,scrollReveal )
})
